import { Caller } from "../core/call/Caller";
import { ResourceManager } from "./ResourceManager";
import { Log } from "../debug/Log";
import { ResourceInfo } from "info/ResourceInfo";
import { PreLoaderManager } from "./PreLoaderManager";
import { FileType } from "./FileType";
import { ObjectPool } from "../utils/pools/ObjectPool";
import { LoaderErrorEvent } from "loader/LoaderErrorEvent";
import { BaseLoader } from "loader/BaseLoader";
import { CacheManager } from "../manager/CacheManager";
type int = number;
//class LoaderManager
    
    export  class LoaderManager
    {
        constructor()
        {
            
            this._dicReference = new Map<any, any> /* flash.utils.Dictionary */();
            if (LoaderManager._instance != null) 
            {
                throw new Error("LoaderManager 单例  ");
            }
            this._queueArray = [];
            this._highQueue = [];
            this._completeCaller = new Caller();
            this._progressCaller = new Caller();
            this._errorCaller = new Caller();
            return;
        }

        public load(arg1: string, arg2: Function, arg3: int=3, arg4: Object=null, arg5: Function=null, arg6: Function=null): void
        {
            var loc1;
            if ((loc1 = ResourceManager.getInfoByName(arg1)) == null) 
            {
                Log.error(arg1 + "==没有该文件");
                if (typeof arg6 === "function") 
                {
                    arg6(loc1);
                }
                return;
            }
            this.loadInfo(loc1, arg2, arg3, arg4, arg5, arg6);
            return;
        }

        public removeNotLoadedFile(arg1: string): void
        {
            var loc1=null;
            var loc2=0;
            loc2 = 0;
            while (loc2 < this._queueArray.length) 
            {
                loc1 = this._queueArray[loc2] as ResourceInfo;
                if (loc1.name == arg1) 
                {
                    this._queueArray.splice(loc2, 1);
                    loc1.isLoading = false;
                    loc1.isLoaded = false;
                    return;
                }
                ++loc2;
            }
            loc2 = 0;
            while (loc2 < this._highQueue.length) 
            {
                loc1 = this._highQueue[loc2] as ResourceInfo;
                if (loc1.name == arg1) 
                {
                    this._highQueue.splice(loc2, 1);
                    loc1.isLoading = false;
                    loc1.isLoaded = false;
                    return;
                }
                ++loc2;
            }
            return;
        }

        public loadInfo(arg1: ResourceInfo, arg2: Function, arg3: int=3, arg4: Object=null, arg5: Function=null, arg6: Function=null): void
        {
            if (arg4) 
            {
                arg1.extData = arg4;
            }
            if (arg1.isLoaded) 
            {
                arg2(arg1);
                arg1.addReference();
                return;
            }
            if (arg1.isLoading) 
            {
                this._completeCaller.addCall(arg1.name, arg2);
                if (typeof arg5 === "function") 
                {
                    this._progressCaller.addCall(arg1.name, arg5);
                }
                if (typeof arg6 === "function") 
                {
                    this._errorCaller.addCall(arg1.name, arg6);
                }
            }
            else if (arg1.isPreLoading) 
            {
                if (!this._preloadingInfo) 
                {
                    this._preloadingInfo = arg1;
                    this._completeCaller.addCall(arg1.name, arg2);
                    if (typeof arg5 === "function") 
                    {
                        this._progressCaller.addCall(arg1.name, arg5);
                    }
                    if (typeof arg6 === "function") 
                    {
                        this._errorCaller.addCall(arg1.name, arg6);
                    }
                    PreLoaderManager.instance.addLoadedCall(arg1.name, this.loadPreRes);
                    PreLoaderManager.instance.addErrorCall(arg1.name, this.loadPreRes);
                }
            }
            else 
            {
                this._completeCaller.addCall(arg1.name, arg2);
                if (typeof arg5 === "function") 
                {
                    this._progressCaller.addCall(arg1.name, arg5);
                }
                if (typeof arg6 === "function") 
                {
                    this._errorCaller.addCall(arg1.name, arg6);
                }
                this.addLoader(arg1, arg3);
            }
            return;
        }

        /* internal  */loadPreRes(): void
        {
            if (this._preloadingInfo) 
            {
                this.loadResource(this._preloadingInfo, true);
                this._preloadingInfo = null;
            }
            return;
        }

        /* internal  */loadResource(arg1: ResourceInfo, arg2: Boolean=false): Boolean
        {
            var loc1=null;
            var loc2=null;
            if (this._currentCount < this.maxQueue || arg2) 
            {
                loc1 = FileType.getLoaderByType(arg1.type);
                if (loc1) 
                {
                    (loc2 = ObjectPool.getObject(loc1)).addEventListener(flash.events.Event.COMPLETE, this.onCompleteHandler);
                    loc2.addEventListener(flash.events.ProgressEvent.PROGRESS, this.onProgressHandler);
                    loc2.addEventListener(LoaderErrorEvent.LoaderError, this.onIOErrorHandler);
                    loc2.load(arg1.path, arg1);
                    var loc3;
                    var loc4=((loc3 = this)._currentCount + 1);
                    loc3._currentCount = loc4;
                    arg1.isLoading = true;
                }
                else 
                {
                    throw new Error("未知的文件类型");
                }
                return true;
            }
            return false;
        }

        /* internal  */addLoader(arg1: ResourceInfo, arg2: int=3): void
        {
            if (this.loadResource(arg1) == false) 
            {
                this.addQueue(arg1, arg2);
                arg1.isLoading = true;
            }
            return;
        }

        /* internal  */addQueue(arg1: ResourceInfo, arg2: int=0): void
        {
            if (arg1.isLoadedByteArray() || arg1.isHasLoaded) 
            {
                arg2 = 0;
            }
            if (arg2 >= 3) 
            {
                this._queueArray.push(arg1);
            }
            else if (arg2 != 0) 
            {
                if (arg2 != 1) 
                {
                    if (arg2 == 2) 
                    {
                        this._queueArray.unshift(arg1);
                    }
                }
                else 
                {
                    this._highQueue.push(arg1);
                }
            }
            else 
            {
                this._highQueue.unshift(arg1);
            }
            return;
        }

        /* internal  */shiftQueue(): ResourceInfo
        {
            if (this._highQueue.length > 0) 
            {
                return this._highQueue.shift() as ResourceInfo;
            }
            if (this._queueArray.length > 0) 
            {
                return this._queueArray.shift() as ResourceInfo;
            }
            return null;
        }

        /* internal  */onCompleteHandler(arg1: Object /* flash.events.Event */): void
        {
            var loc2;
            var loc3=((loc2 = this)._currentCount - 1);
            loc2._currentCount = loc3;
            var loc1=arg1.target as BaseLoader;
            loc1.removeEventListener(flash.events.Event.COMPLETE, this.onCompleteHandler);
            loc1.removeEventListener(flash.events.ProgressEvent.PROGRESS, this.onProgressHandler);
            loc1.removeEventListener(LoaderErrorEvent.LoaderError, this.onIOErrorHandler);
            if (loc1.resourceInfo) 
            {
                loc1.resourceInfo.addReference();
                this._completeCaller.call(loc1.resourceInfo.name, loc1.resourceInfo);
                this._completeCaller.removeCallByType(loc1.resourceInfo.name);
                this._progressCaller.removeCallByType(loc1.resourceInfo.name);
                this._errorCaller.removeCallByType(loc1.resourceInfo.name);
                if (this._dicReference.hasOwnProperty(loc1.resourceInfo.name)) 
                {
                    delete this._dicReference[loc1.resourceInfo.name];
                }
            }
            loc1.dispose();
            ObjectPool.disposeObject(loc1);
            flash.utils.setTimeout(this.loadNext, 100);
            return;
        }

        /* internal  */loadNext(): void
        {
            if (this._highQueue.length > 0) 
            {
                if (this.loadResource(this._highQueue[0] as ResourceInfo)) 
                {
                    this._highQueue.shift();
                }
            }
            else if (this._queueArray.length > 0) 
            {
                if (this.loadResource(this._queueArray[0] as ResourceInfo)) 
                {
                    this._queueArray.shift();
                }
            }
            else if (!this._preloadingInfo) 
            {
                PreLoaderManager.instance.start();
            }
            return;
        }

        /* internal  */onProgressHandler(arg1: Object /* flash.events.ProgressEvent */): void
        {
            var loc1=arg1.target as BaseLoader;
            if (loc1.resourceInfo) 
            {
                this._progressCaller.call(loc1.resourceInfo.name, arg1);
            }
            return;
        }

        /* internal  */onIOErrorHandler(arg1: LoaderErrorEvent): void
        {
            var loc2;
            var loc3=((loc2 = this)._currentCount - 1);
            loc2._currentCount = loc3;
            var loc1=arg1.target as BaseLoader;
            if (loc1.resourceInfo) 
            {
                loc1.resourceInfo.path = loc1.resourceInfo.path + "_1";
                loc1.resourceInfo.dispose();
                this._errorCaller.call(loc1.resourceInfo.name, loc1.resourceInfo);
                this._completeCaller.removeCallByType(loc1.resourceInfo.name);
                this._progressCaller.removeCallByType(loc1.resourceInfo.name);
                this._errorCaller.removeCallByType(loc1.resourceInfo.name);
                CacheManager.instance.deleteVersion(loc1.resourceInfo.name);
                Log.error("LoaderManager.onIOErrorHandler ->" + arg1.text);
            }
            loc1.dispose();
            ObjectPool.disposeObject(loc1);
            this.loadNext();
            return;
        }

        public removeResourceEvent(arg1: string, arg2: Function, arg3: Function=null, arg4: Function=null): void
        {
            if (typeof arg2 === "function") 
            {
                this._completeCaller.removeCall(arg1, arg2);
            }
            if (typeof arg3 === "function") 
            {
                this._progressCaller.removeCall(arg1, arg3);
            }
            if (typeof arg4 === "function") 
            {
                this._errorCaller.removeCall(arg1, arg4);
            }
            return;
        }

        public isLoading(): Boolean
        {
            return !(this._currentCount == 0);
        }

        public disposeFile(arg1: string): void
        {
            var loc1=ResourceManager.getInfoByName(arg1);
            if (loc1) 
            {
                loc1.dispose();
            }
            return;
        }

        public addReference(arg1: string): void
        {
            var loc1=ResourceManager.getInfoByName(arg1);
            if (loc1 && loc1.isHasLoaded) 
            {
                return;
            }
            if (this._dicReference.hasOwnProperty(arg1)) 
            {
                var loc2;
                var loc3;
                var loc4=((loc2 = this._dicReference)[loc3 = arg1] + 1);
                loc2[loc3] = loc4;
            }
            else 
            {
                this._dicReference[arg1] = 1;
            }
            return;
        }

        public removeReference(arg1: string): void
        {
            var loc1=null;
            if (this._dicReference.hasOwnProperty(arg1)) 
            {
                loc1 = ResourceManager.getInfoByName(arg1);
                if (loc1 && !loc1.isHasLoaded) 
                {
                    var loc2;
                    var loc3;
                    var loc4=((loc2 = this._dicReference)[loc3 = arg1] - 1);
                    loc2[loc3] = loc4;
                    if (this._dicReference[arg1] == 0) 
                    {
                        this.clearLoadFile(arg1);
                    }
                }
            }
            return;
        }

        public clearLoadFile(arg1: string): void
        {
            var loc1=this._queueArray.indexOf(arg1);
            if (loc1 == -1) 
            {
                loc1 = this._highQueue.indexOf(arg1);
                this._highQueue.splice(loc1, 1);
            }
            else 
            {
                this._queueArray.splice(loc1, 1);
            }
            return;
        }

        public static get instance(): LoaderManager
        {
            return LoaderManager._instance;
        }

        private /* var */_completeCaller: Caller;

        private /* var */_progressCaller: Caller;

        private /* var */_errorCaller: Caller;

        public /* var */maxQueue: int=8;

        private /* var */_queueMap: Map<any, any> /* flash.utils.Dictionary */;

        private /* var */_currentCount: int=0;

        private /* var */_queueArray: Array<any>;

        private /* var */_highQueue: Array<any>;

        private /* var */_preloadingInfo: ResourceInfo;

        private /* var */_dicReference: Map<any, any> /* flash.utils.Dictionary */;

        private static /* var */_instance: LoaderManager;
    }

            LoaderManager._instance = new LoaderManager();
        